<?php
/** 命令对象的接口 */
interface Command
{
    /** @return bool */
    public function execute();
}
/** 命令接收者 */
class Receiver
{
    public function open()
    {
        echo "Receiver:open\r\n";
    }
    public function close()
    {
        echo "Receiver:close\r\n";
    }
}
/** 调用命令者 */
class Invoker
{
    /** @var Command $command */
    public $command;
    public function setCommand($command)
    {
        $this->command = $command;
        return $this;
    }
    public function doCommand()
    {
        return $this->command->execute();
    }
}

/** 具体的命令 */
class OpenCommand implements Command
{
    /** @var Receiver $receiver */
    public $receiver;
    public function __construct($receiver)
    {
        $this->receiver = $receiver;
    }
    public function execute()
    {
        $this->receiver->open();
    }
}
class CloseCommand implements Command
{
    /** @var Receiver $receiver */
    public $receiver;
    public function __construct($receiver)
    {
        $this->receiver = $receiver;
    }
    public function execute()
    {
        $this->receiver->close();
    }
}

/** 改进的调用者，将命令放入队列 */
class QueueInvoker
{
    /** @var Command[] $commands */
    public $commands;
    public function setCommand($command)
    {
        $this->commands[] = $command;
        return $this;
    }
    public function doCommand()
    {
        while ($this->commands) {
            /** @var Command $command */
            $command = array_shift($this->commands);
            $command->execute();
        }
        return $this->command->execute();
    }
}

header('Content-Type: text/plain');

$receiver = new Receiver;
$invoker = new Invoker;
$invoker->setCommand(new OpenCommand($receiver))->doCommand();
$invoker->setCommand(new CloseCommand($receiver))->doCommand();

$queue = new QueueInvoker;
$queue->setCommand(new OpenCommand($receiver))->setCommand(new CloseCommand($receiver))->doCommand();
